#include "bitonicsort.h"

BitonicSort::BitonicSort(int threadCnt){
    this->threadCnt = threadCnt;
}

void BitonicSort::sort(Array *arr)
{
    this->a = arr->getArray();
    this->sortImpl(arr->getCnt());
    this->a = NULL; // Reset the array
}

void BitonicSort::sortImpl(unsigned long cnt)
{
    unsigned long i, j, k;
    unsigned int threadCount = this->threadCnt;
    int tmp;
    int * arr = this->a;
    #pragma omp parallel shared(arr, k, j, threadCount) private(i, tmp)
    for (k = 2; k <= cnt; k <<= 1)
    {
        for (j = k >> 1; j > 0; j >>= 1)
        {
            #pragma omp for schedule(dynamic, threadCount) nowait
            for (i = 0; i < cnt; i++)
            {
                unsigned long ixj = i ^ j;
                if ((ixj) > i) {
                    if ((i & k) == 0 && arr[i] > arr[ixj])
                    {
                        tmp = arr[i];
                        arr[i] = arr[ixj];
                        arr[ixj] = tmp;
                    }
                    if ((i & k) != 0 && arr[i] < arr[ixj])
                    {
                        tmp = arr[i];
                        arr[i] = arr[ixj];
                        arr[ixj] = tmp;
                    }
                }
            }
        }
    }
}
